package com.gee.spring.boot.influxdb.core;

import com.gee.spring.boot.influxdb.core.enums.AscDesc;
import com.gee.spring.boot.influxdb.core.query.LambdaQuery;
import com.gee.spring.boot.influxdb.core.query.domain.Page;
import com.gee.spring.boot.influxdb.core.util.InfluxdbUtil;
import org.influxdb.InfluxDB;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

import static com.gee.spring.boot.influxdb.core.util.InfluxdbUtil.getCount;

/**
 * @author gepengjun
 * @since 2024/4/24 14:11
 */
public class InfluxdbTemplate {

    private static final Logger logger = LoggerFactory.getLogger(InfluxdbUtil.class);

    @Autowired
    private InfluxDB influxDB;

    private final String database;

    public InfluxdbTemplate(String database) {
        this.database = database;
    }

    @PostConstruct
    public void init(){
        influxDB.setDatabase(database);
    }

    /***
     * 默认执行方法
     * @param query  sql语句
     * @return QueryResult
     */
    public QueryResult execute(String query) {
        logger.info("sql: {}", query);
        return influxDB.query(new Query(query, database));
    }

    public <T> T latest(Class<T> entityClass){
        LambdaQuery<T> lambdaQuery = LambdaQuery.newQuery(entityClass).orderBy("time", AscDesc.DESC).limit(1L);
        List<T> list = list(lambdaQuery);
        return list.isEmpty() ? null : list.get(0);
    }

    public <T> List<T> list(LambdaQuery<T> query) {
        return InfluxdbUtil.toPOJO(execute(query.toSqlStr()), query.getEntityClass(), query.getFuncTime());
    }

    /**
     * 查询 返回对应实体 List
     *
     * @param query sql语句
     * @param clazz 实体
     * @param <T>
     * @return
     */
    public <T> List<T> list(String query, Class<T> clazz) {
        return list(query, clazz, false);
    }

    public <T> List<T> list(String query, Class<T> clazz, boolean funcTime) {
        return InfluxdbUtil.toPOJO(execute(query), clazz, funcTime);
    }

    public <T> Page<T> page(LambdaQuery<T> query , Page<T> page) {
        QueryResult countResult = execute(query.toCountSql());
        page.setTotal(getCount(countResult));
        page.setDataList(list(query));
        return page;
    }

    /**
     * 批量插入
     *
     * @param entity 实体
     */
    public void batchInsert(List<?> entity) {
        List<String> data = new ArrayList<>();
        for (Object object : entity) {
            data.add(InfluxdbUtil.toPoint(object).lineProtocol());
        }
        influxDB.write(data);
    }

    public void insert(Object entity) {
        influxDB.write(InfluxdbUtil.toPoint(entity));
    }
}
